package com.czh.zhiwen.scoring;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.czh.zhiwen.common.AiRequest;
import com.czh.zhiwen.model.dto.question.QuestionAnswerDTO;
import com.czh.zhiwen.model.dto.question.QuestionContentDTO;
import com.czh.zhiwen.model.entity.App;
import com.czh.zhiwen.model.entity.Question;
import com.czh.zhiwen.model.entity.UserAnswer;
import com.czh.zhiwen.model.vo.QuestionVO;
import com.czh.zhiwen.service.QuestionService;
import com.czh.zhiwen.service.ScoringResultService;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.cli.Digest;
import org.apache.commons.codec.digest.DigestUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@ScoringStrategyConfig(appType = 1,scoringStrategy = 1)
public class AiTestScoringStrategyImpl implements ScoringStrategy {

    @Resource
    private  QuestionService questionService;

    @Resource
    private AiRequest aiRequest;

    /**
     * AI评分结果本地缓存
     */
    private final Cache<String,String> answerCache =
            // 缓存大小1024
            Caffeine.newBuilder().initialCapacity(1024)
                    // 过期时间5分钟
                    .expireAfterAccess(5L, TimeUnit.MINUTES)
                    .build();

    /**
     * AI评分系统消息
     */
    public static final String SYSTEM_MESSAGE = "你是一位严谨的判题专家，我会给你如下信息：\n" +
            "```\n" +
            "应用名称，\n" +
            "【【【应用描述】】】，\n" +
            "题目和用户回答的列表：格式为 [{\"title\": \"题目\",\"answer\": \"用户回答\"}]\n" +
            "```\n" +
            "\n" +
            "请你根据上述信息，按照以下步骤来对用户进行评价：\n" +
            "1. 要求：需要给出一个明确的评价结果，包括评价名称（尽量简短）和评价描述（尽量详细，大于 200 字）\n" +
            "2. 严格按照下面的 json 格式输出评价名称和评价描述\n" +
            "```\n" +
            "{\"resultName\": \"评价名称\", \"resultDesc\": \"评价描述\"}\n" +
            "```\n" +
            "3. 返回格式必须为 JSON 对象\n";


    /**
     * Ai评分用户消息封装
     * @param app
     * @param questionAnswerDTOList
     * @param choices
     * @return
     */
    private String getAiTestScoringUserMessage(App app,List<QuestionContentDTO> questionAnswerDTOList , List<String> choices){
        StringBuilder userMessage = new StringBuilder();
        userMessage.append(app.getAppName()).append("\n");
        userMessage.append(app.getAppDesc()).append("\n");
        List<QuestionAnswerDTO> list = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            QuestionAnswerDTO questionAnswerDTO = new QuestionAnswerDTO();
            questionAnswerDTO.setTitle(questionAnswerDTOList.get(i).getTitle());
            questionAnswerDTO.setUserAnswer(choices.get(i));
            list.add(questionAnswerDTO);
        }
        userMessage.append(JSONUtil.toJsonStr(list));
        return userMessage.toString();
    }

    /**
     * 根据用户选择的答案，让AI来对比题目的答案来进行评分
     * @param choices
     * @param app
     * @return
     * @throws Exception
     */
    @Override
    public UserAnswer doScore(List<String> choices, App app) throws Exception {
        Long appid = app.getId();
        String jsonStr = JSONUtil.toJsonStr(choices);
        // 构建缓存的key值
        String cacheKey = buildCacheKey(appid, jsonStr);
        // 先从缓存查询获取评分结果
        String answerJson = answerCache.getIfPresent(cacheKey);
        // 如果缓存中存在，则直接返回
        if(StrUtil.isNotBlank(answerJson)){
            UserAnswer userAnswer = JSONUtil.toBean(answerJson, UserAnswer.class);
            userAnswer.setAppId(app.getId());
            userAnswer.setAppType(app.getAppType());
            userAnswer.setScoringStrategy(app.getScoringStrategy());
            userAnswer.setChoices(jsonStr);
            return userAnswer;

        }
        // 1、根据id查询题目和题目的答案
        Question question = questionService.getOne(
                Wrappers.lambdaQuery(Question.class)
                        .eq(Question::getAppId, appid));
        QuestionVO questionVO = QuestionVO.objToVo(question);
        List<QuestionContentDTO> questionContent = questionVO.getQuestionContent();
        // 2、调用AI评分系统评分
        //封装prompt
        String userMessage = getAiTestScoringUserMessage(app, questionContent, choices);
        String result = aiRequest.doAiRequest(SYSTEM_MESSAGE, userMessage);
        int start = result.indexOf("{");
        int end = result.lastIndexOf("}");
        String jsonstr = result.substring(start, end + 1);

        // 缓存评分结果
        answerCache.put(cacheKey, jsonstr);
        //3、返回评分结果,设置属性
        UserAnswer userAnswer = JSONUtil.toBean(jsonstr, UserAnswer.class);
        userAnswer.setAppId(app.getId());
        userAnswer.setAppType(app.getAppType());
        userAnswer.setScoringStrategy(app.getScoringStrategy());
        userAnswer.setChoices(jsonStr);
        return userAnswer;
    }

    /**
     * 构建缓存的key值
     * @param appId
     * @param choices
     * @return
     */
    private String buildCacheKey(Long appId,String choices){
        return DigestUtils.md5Hex(appId + ":" + choices);
    }



}
